/**
 * kl yy-ds @2021
 */
package com.cxps.server.product.service;

import com.alibaba.fastjson.JSON;
import com.cxps.cloud.common.ConstantPool;
import com.cxps.server.product.domain.ProductEntity;
import com.cxps.server.product.domain.ProductIndex;
import com.cxps.server.product.mapper.ProductMapper;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.support.WriteRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.Requests;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermsQueryBuilder;
import org.elasticsearch.index.reindex.DeleteByQueryRequest;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 商品 业务逻辑层
 *
 * @author YouCai.Liu
 * @since 2021/11/12
 * ...
 */
@Slf4j
@Service
public class ProductService {

    @Autowired
    private ProductMapper productMapper;

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    @Autowired
    private RedisTemplate redisTemplate;

    @Value("${cxps.yyds.product_index_name}")
    private String indexName;

    /**
     * 将商品在MySQL里的数据转换到ES索引里
     */
    public void batchEs() {

        // 创建一个 ES索引请求的 对象
        IndexRequest indexRequest = Requests.indexRequest(indexName);

        // 去数据库查询商品数据
        // TODO: 2021/11/12
        /**
         * 数据量如果特别多，多线程加分页去批量处理。
         * 如果数据量一般，查询所有数据到内存里，要有异常的处理，防止影响大局。
         * 如果数据量少，就可以慢慢的去做
         */
        List<ProductEntity> entityList = productMapper.selectAllProduct();
        for (ProductEntity entity : entityList) {
            try {
                // 索引对象
                ProductIndex index = new ProductIndex();
                BeanUtils.copyProperties(entity, index);

                List<String> fullTextList = new ArrayList<>();
                fullTextList.add(entity.getProductName());
                fullTextList.add(entity.getProductType());
                index.setFullText(fullTextList);

                // 设置文档ID
                indexRequest.id(entity.getId());

                // 将对象转换json
                indexRequest.source(JSON.toJSONString(index), XContentType.JSON);
                indexRequest.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE);

                // 发起请求
                restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
            } catch (Exception e) {
                log.error(entity.getId() + " >>> 插入到ES异常：" + e.getMessage(), e);
            }
        }
    }

    /**
     * 将商品分类缓存到Redis
     */
    public void cacheProductType() {
        // 查询商品分类
        List<String> strList = productMapper.selectProductTypeAll();

        StringBuilder sb = new StringBuilder();
        for (String str : strList) {
            sb.append(str).append(",");
        }
        String type = sb.toString();
        String substring = type.substring(0, type.length() - 1);

        // 缓存到redis
        ValueOperations valueOperations = redisTemplate.opsForValue();
        valueOperations.set(ConstantPool.R_PRODUCT_TYPE, substring);
    }

    /**
     * 获取redis缓存
     *
     * @return
     */
    public String getCache(String key) {
        ValueOperations valueOperations = redisTemplate.opsForValue();
        Object productType = valueOperations.get(key);
        if (null == productType) {
            return null;
        }
        return productType.toString();
    }

    /**
     * 根据ID集合将数据同步到ES
     *
     * @param ids
     */
    public void batchEsByIds(String[] ids) {

        // 根据ID查询要同步的商品数据
        List<ProductEntity> entityList = productMapper.selectBatchIds(Arrays.asList(ids));

        if (null == entityList || entityList.isEmpty()) {
            return;
        }

        // 创建一个 ES索引请求的 对象
        IndexRequest indexRequest = Requests.indexRequest(indexName);

        // 去数据库查询商品数据
        for (ProductEntity entity : entityList) {
            try {
                // 索引对象
                ProductIndex index = new ProductIndex();
                BeanUtils.copyProperties(entity, index);

                // 设置文档ID
                indexRequest.id(entity.getId());

                // 将对象转换json
                indexRequest.source(JSON.toJSONString(index), XContentType.JSON);
                indexRequest.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE);

                // 发起请求
                restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
            } catch (Exception e) {
                log.error(entity.getId() + " >>> 插入到ES异常：" + e.getMessage(), e);
            }
        }

    }

    /**
     * 根据ID删除ES数据
     *
     * @param ids
     */
    public void delEsByIds(String[] ids) throws IOException {
        // 创建一个 删除ES索引数据请求的 对象
        DeleteByQueryRequest deleteByQueryRequest = new DeleteByQueryRequest(indexName);
        TermsQueryBuilder termsQuery = QueryBuilders.termsQuery("id", ids);
        deleteByQueryRequest.setQuery(termsQuery);
        restHighLevelClient.deleteByQuery(deleteByQueryRequest, RequestOptions.DEFAULT);
    }
}
